import { AuthService } from "./business/auth";
import { LcPageService } from "./business/lc-page";
// import { PermissionService } from "./business/permission";
// import { RoleService } from "./business/role";
import { UserService } from "./business/user";
import { BcryptService } from "./vendor/bcrypt";
import { JsonwebtokenService } from "./vendor/jsonwebtoken";
// import { NodemailerService } from "./vendor/nodemailer";
import { OssService } from "./vendor/oss";
// import { RedisCacheService } from "./vendor/redis/cache";
// import { RedisUserService } from "./vendor/redis/user";

const serviceMap = {
  BcryptService,
  // RedisUserService,
  // RedisCacheService,
  OssService,
  JsonwebtokenService,
  // NodemailerService,
  AuthService,
  UserService,
  // RoleService,
  // PermissionService,
  LcPageService,
} as const;

// type ServiceMap = typeof serviceMap;

// 映射每个服务名称到其实例类型
// type ServiceInstances = {
//   [K in keyof ServiceMap]: InstanceType<ServiceMap[K]>;
// };

/**
 * 避免循环service循环依赖的问题
 * 【服务注册中心，全部 service 采用单例】
 */
class Container<T extends Record<string, new (...args: any[]) => any>> {
  private services = new Map<keyof T, any>();

  constructor(serviceMap: T) {
    for (const name in serviceMap) {
      const Cls = serviceMap[name];
      const dependencies = this.getDependencies(Cls);
      this.services.set(name, new Cls(...dependencies));
    }
  }

  resolve<K extends keyof T>(name: K): InstanceType<T[K]> {
    const service = this.services.get(name);
    if (!service) throw new Error(`Service ${String(name)} not found`);
    return service;
  }

  all(): {
    [K in keyof T]: InstanceType<T[K]>;
  } {
    const result = {} as any;
    for (const [key, value] of this.services) {
      result[key] = value;
    }
    return result;
  }

  private getDependencies(cls: new (...args: any[]) => any): any[] {
    const paramNames = this.getConstructorParams(cls);
    return paramNames.map((name) => this.resolve(name as keyof T));
  }

  private getConstructorParams(cls: new (...args: any[]) => any): string[] {
    const match = cls.toString().match(/constructor\(([^)]*)\)/);
    if (!match) return [];
    return match[1]
      .split(",")
      .map((p) => p.trim().replace(/(^\w)/, (char) => char.toUpperCase()))
      .filter(Boolean);
  }
}

export const container = new Container(serviceMap);
